/**
* Service Base contains all the network methods to fire middleware requests.
* @module baseService
* @requires jquery
* @requires baseModel
* @requires framework/js/constants/constants
* @requires platform
*/
define([
'jquery',
'baseModel',
'framework/js/constants/constants',
'platform'
], function ($, BaseModel, Constants, Platform) {
'use strict';
/**
* Service Base contains all the network methods to fire middleware requests.
* @class
* @alias BaseService
* @memberof module:baseService
* @hideconstructor
*/
var BaseService = function () {
/**
* Assign this to self.
* @member {Object}
*/
var self = this;
/**
* Creates a map of requests to handle repost.
* @member {Object}
*/
var map = {};
/**
* Creates a map of eTags per request URL.
* @member {Object}
*/
var eTags = {};
/**
* Holds the current active request count.
* @member {Number}
*/
var counter = 0;
/**
* Array to hold the nonce values to be set for each middleware request.
* @member {Array}
*/
var nonceKeys = [];
/**
* Instance of [BaseKOModel]{@linkcode BaseKOModel}.
* @member {BaseKOModel}
*/
var baseModel = BaseModel.getInstance();
/**
* Boolean to determine whether the request is a mock request.
* @type {Boolean}
*/
var isMocked = false;
/**
* Stores the base URL of the middleware request, uses local JSON path if request is mocked.
* Uses [appBaseURL]{@linkcode Constants.appBaseURL} to determine middleware root URL.
* @type {String}
*/
var baseUrl = isMocked ? '../json/' : Constants.appBaseURL;
/**
* Boolean to enable/disable nonce.
* @type {Boolean}
*/
var nonceEnabled = true;
/**
* Stores success/failure for batch requests.
* @type {Boolean}
*/
var batchSuccess = true;
/**
* Hold the platform properties.
* @type {function}
*/
var platform;
/**
* Array of jQuery [Deferred]{@linkcode http://api.jquery.com/category/deferred-object/} to hold state of nonce request.
* @type {Array.}
*/
var isNonceFetched = [];
/**
* A boolean which holds the state for current pending nonce.
* @type {Boolean}
*/
var isNoncePending = false;
/**
* A boolean which holds the state for current pending authentication.
* @type {Boolean}
*/
var isOn417 = false;
var counterAjax = 0;
/**
* This function return the resource URL.
* @function getResourceURL
* @memberof BaseService
* @inner
* @param {String} url URL String
* @param {String} [version] version of the application
* @return {String} resource URL
*/
var getResourceURL = function (url, version) {
var serverURL = platform('getServerURL');
if (serverURL) {
return serverURL + baseUrl + '/' + (version || Constants.appDefaultVersion) + '/' + url;
}
return baseUrl + '/' + (version || Constants.appDefaultVersion) + '/' + url;
};
/**
* This function return the resource path.
* @function getResourcePath
* @memberof BaseService
* @inner
* @param {String} url URL String
* @param {String} [version] version of the application
* @return {String} resource path
*/
// getResourcePath = function (url, version) {
// var serverURL = platform("getServerURL");
// if (serverURL) {
// url = url.replace(serverURL + baseUrl, "").replace("/" + version + "/", "/");
// }
//
// if (url.includes('scb')) {
// url = url.replace(baseUrl, "").replace("/scb", "").replace("/" + version + "/", "/");
// }
//
// return url.replace(baseUrl, "").replace("/" + version + "/", "/");
// },
var getResourcePath = function (url, version) {
var serverURL = platform('getServerURL');
if (serverURL) {
url = url.replace(serverURL + baseUrl, '').replace('/' + version + '/', '');
}
if (url.includes('scb')) {
url = url.replace(baseUrl, '').replace('/scb', '').replace('/' + version + '/', '');
}
return url.replace(baseUrl, '').replace('/' + version + '/', '');
};
/**
* This function strips out empty query parameters from the URL.
* @function normalizeURL
* @memberof BaseService
* @inner
* @param {String} url The URL to clean.
* @return {String} Normalized URL is returned.
*/
var normalizeURL = function (url) {
if (url.split('?').length > 1) {
return url.split('?')[0] + '?' + url.split('?').pop().replace(/(&?)\w+=(?:&|undefined(&)?|null(&)?|$)/g, '$1').replace(/&$/, '');
}
return url;
};
/**
* This function appends user-locale information to all outgoing network requests.
* Uses [add]{@linkcode BaseModel} method from QueryParams to append locale query parameter picked from current user locale from oj.Config.getLocale().
* @function addUserLocale
* @memberof BaseService
* @inner
* @param {String} url The URL to which user-locale query parameter is to be added.
* @return {String} Returns the URL with locale query parameter which holds user-locale code.
*/
var addUserLocale = function (url) {
return baseModel.QueryParams.add(url, {
locale: baseModel.getLocale()
});
};
/**
* The generic function which serves as completeHandler for all ajax requests.
* @function genericCompleteHandler
* @inner
* @memberof BaseService
* @param {jQuery.jqXHR} jqXHR The jqXHR object returned from jQuery [ajax]{@linkcode http://api.jquery.com/jquery.ajax/} call.
* @param {String} textStatus The string categorizing the status of the request viz.
"success", "notmodified", "nocontent", "error", "timeout", "abort", or "parsererror"
* For more details, see [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings}.
* @returns {void}
*/
var genericCompleteHandler = function (jqXHR, textStatus) {
var eTag;
if (this && this.type !== "GET") {
delete map[this.type + this.url];
}
batchSuccess = true;
var key = JSON.parse(jqXHR.getResponseHeader("x-nonce"));
if (key && key.hasOwnProperty("nonce")) {
nonceKeys = nonceKeys.concat(JSON.parse(jqXHR.getResponseHeader("x-nonce")).nonce);
nonceEnabled = true;
} else {
nonceEnabled = false;
}
if (this && this.url && this.type === "GET") {
eTag = jqXHR.getResponseHeader("ETag");
if (eTag) {
eTags[this.url] = eTag;
}
}
Constants.currentServerDate.setTime(new Date(jqXHR.getResponseHeader("Date")).getTime());
/*
if (jqXHR.status === 403) {
var options = {};
options.url = "me";
options.type = "GET";
options.contentType = "application/json";
options.complete = function (jqXHR1) {
if (jqXHR1.status === 401) {
//location.reload();
}
};
if (getResourceURL("me", this.version) !== this.url) {
// Noncompliant@+1 {{Move the declaration of "fireAjax" before this usage.}}
// eslint-disable-next-line no-use-before-define
fireAjax(options, {});
}
}
if (jqXHR.getResponseHeader("BATCH_ID")) {
for (var i = 0; i < jqXHR.responseJSON.batchDetailResponseDTOList.length; i++) {
key = JSON.parse(jqXHR.responseJSON.batchDetailResponseDTOList[i].header["x-nonce"] || "{}");
if (key && key.hasOwnProperty("nonce")) {
nonceKeys.push(key.nonce[0]);
}
if (jqXHR.responseJSON.batchDetailResponseDTOList[i].status >= 400) {
batchSuccess = false;
}
}
if (!batchSuccess) {
baseModel.showMessages(jqXHR);
}
} else {
if (this.showMessage && isOn417) {
if (jqXHR.status === 400) {
baseModel.showMessages(jqXHR, null, null, function () {
location.reload();
isOn417 = false;
});
} else {
baseModel.showMessages(jqXHR);
}
}
if (this.showMessage && !isOn417) {
if (jqXHR.status === 409 || jqXHR.status === 403) {
baseModel.showMessages(jqXHR, null, "ERROR", function () {
location.reload();
});
//location.reload();
} else {
baseModel.showMessages(jqXHR);
}
}
if (textStatus === "timeout" && this.timeoutMessage) {
baseModel.showMessages(null, [this.timeoutMessage], "ERROR");
}
}
if (jqXHR.status === 417) {
jqXHR.abort();
counter--;
this.url = getResourcePath(this.url, this.version);
// Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}}
// eslint-disable-next-line no-use-before-define
baseModel.showAuthScreen(jqXHR, this, (jqXHR.getResponseHeader("boundary") && jqXHR.getResponseHeader("boundary").indexOf("--OBDXbatch") > -1) ? fireBatchAjax : fireAjax, this.success);
isOn417 = true;
$('#button').removeAttr('disabled');
return false;
}
if (this && !this.selfLoader) {
counter--;
}
if (counter === 0) {
setTimeout(function () {
if (counter === 0) {
$(".se-pre-con").fadeOut("slow");
}
}, 100);
baseModel.lastUpdatedTime(new Date());
}
if (jqXHR.status === 409) {
window.location.search = "";
} else if (jqXHR.status === 403) {
var options = {};
options.url = "me";
options.type = "GET";
options.contentType = "application/json";
options.complete = function (jqXHR1) {
if (jqXHR1.status === 401) {
window.location.search = "";
}
};
if (getResourceURL("me", this.version) !== this.url) {
// Noncompliant@+1 {{Move the declaration of "fireAjax" before this usage.}}
// eslint-disable-next-line no-use-before-define
fireAjax(options, {});
}
}
if (jqXHR.getResponseHeader('BATCH_ID')) {
for (var i = 0; i < jqXHR.responseJSON.batchDetailResponseDTOList.length; i++) {
key = JSON.parse(jqXHR.responseJSON.batchDetailResponseDTOList[i].header['x-nonce'] || '{}');
if (key && key.hasOwnProperty('nonce')) {
nonceKeys.push(key.nonce[0]);
}
if (jqXHR.responseJSON.batchDetailResponseDTOList[i].status >= 400) {
batchSuccess = false;
}
}
if (!batchSuccess) {
baseModel.showMessages(jqXHR);
}
} else {
_processLoadingImage(false);
// if (this.showMessage) {
// if (isOn417) {
// if (jqXHR.status === 400) {
// baseModel.showMessages(jqXHR, null, null, function () {
// // location.reload();
// isOn417 = false;
// });
// } else {
// baseModel.showMessages(jqXHR);
// }
// } else if (jqXHR.status === 409 || jqXHR.status === 403) {
// baseModel.showMessages(jqXHR, null, 'ERROR', function () {
// // index. se goi lai trang index. trong do se xoa session & cookie
// window.onbeforeunload = null;
// window.location = 'index.html?module=login';
// });
// } else {
// baseModel.showMessages(jqXHR);
// }
// if (textStatus === 'timeout' && this.timeoutMessage) {
// baseModel.showMessages(null, [this.timeoutMessage], 'ERROR');
// }
// }
if (this.showMessage) {
baseModel.showMessages(jqXHR);
}
if (textStatus === "timeout" && this.timeoutMessage) {
baseModel.showMessages(null, [this.timeoutMessage], "ERROR");
}
}
*/
if (jqXHR.status === 417) {
// jqXHR.abort();
// counter--;
// this.url = getResourcePath(this.url, this.version);
// // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}}
// // eslint-disable-next-line no-use-before-define
// baseModel.showAuthScreen(jqXHR, this, (jqXHR.getResponseHeader('boundary') && jqXHR.getResponseHeader('boundary').indexOf('--OBDXbatch') > -1) ? fireBatchAjax : fireAjax, this.success);
// isOn417 = true;
// $('#button').removeAttr('disabled');
// return false;
// if (this.showMessage) {
// baseModel.showMessages(jqXHR);
// }
counter--;
// Dung 18/02/19
// Handle 417 with error : Vuot qua so lan xac thuc
if ((jqXHR.responseJSON.status && jqXHR.responseJSON.status.message.code === 'DIGX_AUTH_0007') || (jqXHR.responseJSON.message && jqXHR.responseJSON.message.code === 'DIGX_AUTH_0007')) {
baseModel.showMessages(jqXHR, null, null, function () {
history.back();
window.onbeforeunload = null;
});
} else {
if (this.showMessage) {
baseModel.showMessages(jqXHR);
}
// baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success);
this.url = getResourcePath(this.url, this.version);
// Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}}
// eslint-disable-next-line no-use-before-define
// baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success);
baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? self.uploadFile : fireAjax, this.success);
// return false;
}
return false;
// counter--;
// this.url = getResourcePath(this.url, this.version);
// // Noncompliant@+1 {{Move the declaration of "fireBatchAjax" before this usage.}}
// // eslint-disable-next-line no-use-before-define
// baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success);
// // baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? self.uploadFile : fireAjax, this.success);
// return false;
}
if (this && !this.selfLoader) {
counter--;
}
if (counter === 0) {
setTimeout(function () {
if (counter === 0) {
$('.se-pre-con').fadeOut('slow');
}
}, 100);
baseModel.lastUpdatedTime(new Date());
}
};
/**
* Method to fetch nonce keys for base service. This method will fire a
* POST request and based fetch nonce keys from the response header
* and add them to [nonceKeys]{@linkcode BaseService~nonceKeys} array, from which a key is popped and added to each
* going request.
* @function getNonceForServiceInstance
* @memberof BaseService
* @instance
* @param {Number} [nonceCount=15] The number of nonce requested.
* @param {Number} [otp] The OTP for the current request.
* @param {Number} [referenceNumber] Reference Number for the current request.
* @returns {void}
*/
var getNonceForServiceInstance = function (nonceCount) {
if ((nonceEnabled || nonceCount) && (nonceKeys.length < 5 || nonceCount) && !isNoncePending) {
// console.log('--- lay nonce---:' + nonceCount + '---' + nonceKeys.length)
isNoncePending = true;
var options = {};
var currentNonce = $.Deferred();
options.type = 'POST';
// phucnnd them. Goi dong bo
// options.async = false
options.contentType = 'application/json';
options.showMessage = true;
options.headers = {
'x-noncecount': nonceCount || 75
};
options.complete = function (jqXHR) {
genericCompleteHandler.apply(this, [jqXHR]);
currentNonce.resolve();
isNoncePending = false;
// console.log('--- lay nonce xong---noncekey-nonceCount:' + nonceKeys + '--' + nonceCount)
};
$('body').removeClass('loaded');
counter++;
isNonceFetched.push(currentNonce);
Platform.getInstance().then(function (instance) {
platform = instance;
options.url = getResourceURL('session/nonce');
platform('addHeader', options.headers);
options.url = addUserLocale(options.url);
options.url = normalizeURL(options.url);
$.ajax(options);
});
}
};
/**
* This object specifies the default ajax settings for all network calls fired via exported methods of [BaseService]{@linkcode BaseService}.
* See [list]{@linkcode module:baseService} of all such methods.
* @type {Object}
*/
var defaults = {
type: 'GET',
url: '',
async: true,
contentType: 'application/json',
headers: {
'X-Target-Unit': Constants.currentEntity,
// phucnnd update. Cho giong voi ban mobile. Tuy nhien check login ban desktop lai
'X-Channel': Constants.channel
},
dataType: 'json',
showMessage: true,
selfLoader: false,
beforeSend: function (xhr) {
getNonceForServiceInstance();
if (!this.selfLoader) {
counter++;
$('.se-pre-con').show();
}
if (nonceKeys.length > 0) {
var currentNonce = nonceKeys.pop();
xhr.setRequestHeader('x-nonce', currentNonce);
}
if (this.type !== 'GET' && !(this.headers.boundary && this.headers.boundary.indexOf('--OBDXbatch') > -1)) {
if (!((this.type + this.url) in map)) {
map[(this.type + this.url)] = this.type + this.url;
} else {
xhr.abort();
counter--;
}
if (this.url in eTags) {
xhr.setRequestHeader('If-Match', eTags[this.url]);
}
}
},
complete: genericCompleteHandler
};
/**
* This function utilizes [format]{@linkcode BaseModel#format} to parameterize URL.
* Supports same arguments as [format]{@linkcode BaseModel#format}. See its documentation for more details.
* @function parameterizeURL
* @inner
* @memberof BaseService
*/
var parameterizeURL = baseModel.format;
/**
* This function clears the [isNonceFetched]{@linkcode BaseService#isNonceFetched} array based on which deferreds are resolved.
* @function clearIsNonceFetched
* @inner
* @memberof BaseService
*/
var clearIsNonceFetched = function () {
isNonceFetched.forEach(function (deferred, index, array) {
if (deferred.state() === 'resolved') {
array.splice(index, 1);
}
});
};
/**
* The main function which fires the actual ajax request.
* This function is called internally from all the exported methods of [BaseService]{@linkcode BaseService}.
* Returns a promise which resolves/rejects with the network request.
* @function fireAjax
* @memberof BaseService
* @inner
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @return {Promise} Returns the promise which resolves/rejects with the network request.
*/
var fireAjax = function (settings, params) {
//_processLoadingImage(true);
if (settings.nonceRequired) {
nonceEnabled = true;
}
var language = sessionStorage.getItem('user-locale') || document.getElementsByTagName('html')[0].getAttribute('lang') || 'en';
// nonceEnabled = true;
getNonceForServiceInstance();
return new Promise(function (resolve, reject) {
Promise.all(isNonceFetched).then(function () {
clearIsNonceFetched();
defaults.headers['X-Target-Unit'] = Constants.currentEntity;
var options = $.extend(true, {}, defaults, settings);
options.version = options.version || Constants.appDefaultVersion;
// customize
if (!options.externalURL) {
options.url = getResourceURL(options.url, options.version);
}
if (params) {
options.url = parameterizeURL(options.url, params, true);
}
if (settings.versionApp) {
options.url = 'https://ebanking.scb.com.vn/index/json/version.json';
}
options.promiseResolve = resolve;
if (options.url.includes('/batch') === true &&
options.headers.TOKEN_ID !== null) {
// console.log('url.includes(/batch)===true');
// return baseUrl + url;
options.url = "/digx/batch";
}
options.url = addUserLocale(options.url);
options.url = normalizeURL(options.url);
// console.log('---service base--:' + options.url)
if (settings.isCustomize) {
// options.url = self.baseUrlCz + (self.isMocked ? options.url.split('?')[0] : options.url);
options.url = options.url.replace('/digx', '/digx/scb');
} else {
if (settings.isTest) {
options.url = options.url.includes(self.baseUrlCzTest) ? (self.isMocked ? options.url.split('?')[0] : options.url) : self.baseUrlCzTest + (self.isMocked ? options.url.split('?')[0] : options.url);
} else if (settings.isURLthach) {
if (options.url.includes(self.baseUrlCzThach)) {
options.url = options.url.replace(self.baseUrlCzThach, '');
}
options.url = self.baseUrlCzThach + (self.isMocked ? options.url.split('?')[0] : options.url);
} else if (settings.isURLcz1) {
options.url = options.url.replace("/digx/v1", "/digx/cz/v1"); //self.baseUrlCz_1; //options.url.replace(options.url,
} else if (settings.isMode) {
options.url = options.url.replace("/digx/v1", "/digx/v1/scb");
}
}
// phucnnd them tu compare Oracle
platform('addHeader', options.headers);
// console.log('----options.url:' + options.url);
// console.log('----options.headers:' + options.headers);
// phucnnd them
// options.async = false
// 60 giay
// co the gay response tra ve canceled
// options.timeout = 300000;
// var error = options.error;
var success = options.success;
options.success = function (jqXHR, textStatus, data) {
_processLoadingImage(false);
resolve(data, textStatus, jqXHR);
if (success) {
success(jqXHR, textStatus, data);
}
};
// options.error = function (jqXHR, textStatus, data) {
// // _processLoadingImage(false);
// resolve(jqXHR, textStatus, data);
// // if (success) {
// // error(jqXHR, textStatus, data);
// // }
// };
$.ajax(options).done(function (data, textStatus, jqXHR) {
_processLoadingImage(false);
// console.log('---service base--success resolve');
Constants.currentEntity = jqXHR.getResponseHeader("X-Target-Unit");
resolve(data, textStatus, jqXHR);
}).fail(function (jqXHR, textStatus, errorThrown) {
// data
console.log('----jqXHR fail-textStatus-data' + jqXHR + textStatus + errorThrown);
_processLoadingImage(false);
if (jqXHR && jqXHR.status === 400 && jqXHR.readyState === 4) {
// {"result":"SUCCESSFUL","contextID":"005Umf5taHk4YrWjLxJN8A000VQK002xpI,0:1","message":{"title":"Yêu cầu thay đổi mật khẩu.","detail":"Yêu cầu thay đổi mật khẩu.","code":"DIGX_UM_042","type":"ERROR"}}
// II Dung remove show message
// Tìm những trường hợp bị lỗi ko có message từ service để show lên
// DIGX_DDA_049 for get DORMANT account
if (jqXHR.responseJSON !== null && jqXHR.responseJSON.message !== null && jqXHR.responseJSON.message.code === "DIGX_DDA_049") {
// Force change password
_processLoadingImage(false);
resolve(errorThrown, textStatus, jqXHR);
if (success) {
success(jqXHR, textStatus, errorThrown);
}
// Trường hợp là force change password
return true;
} else {
// Error : Yeu cau thay doi mat khau
if (jqXHR.responseJSON.message.code === "DIGX_UM_042") {
reject(jqXHR, textStatus, errorThrown);
baseModel.showMessages(null, [jqXHR.responseJSON.message.detail], 'INFO');
//baseModel.checkAndShowError(jqXHR);
// Error : Loi ko xac dinh : unexpected
} else if (jqXHR.responseJSON.message.code === "DIGX_AUTH_0003") {
reject(jqXHR, textStatus, errorThrown);
}
else if (jqXHR.responseJSON.message.code === "3403") {
baseModel.showMessages(null, ['Có lỗi xảy ra - Xin vui lòng thử lại'], null, function () {
history.back();
window.onbeforeunload = null;
});
// Error when No transaction
} else {
baseModel.checkAndShowError(jqXHR);
}
// else if (jqXHR.responseJSON.message.code === "DIGX_DDA_007"
// || jqXHR.responseJSON.message.code === "DIGX_OR_TD_0012"
// || jqXHR.responseJSON.message.code === "DIGX_LA_0007"
// // Dung cho loi khong lay duoc data cua nhat ki giao dich Maker & Checker
// || jqXHR.responseJSON.message.code === "DIGX_AP_0039") {
// baseModel.showMessages(jqXHR);
// } else {
// baseModel.showMessages(jqXHR, null, null, function () {
// history.back();
// window.onbeforeunload = null;
// });
// }
return false;
}
} else if (jqXHR.status === 403) {
// check lai coi phai loi het session khong.
if (jqXHR.responseJSON.message.code === 'DIGX_PROD_ACCESS_DENIED_0000') {
baseModel.showMessages(jqXHR, null, 'ERROR', function () {
// index. se goi lai trang index. trong do se xoa session & cookie
window.onbeforeunload = null;
window.location = 'index.html?module=login';
});
} else {
reject(jqXHR, textStatus, errorThrown);
}
return false;
} else if (jqXHR.status === 409) {
reject(jqXHR, textStatus, errorThrown);
var _lang = null;
if (language === 'vn') {
_lang = 'Phiên giao dịch của bạn đã hết hiệu lực. Vui lòng đăng nhập lại để tiếp tục.';
} else {
_lang = 'Session is expired. Please login again';
}
baseModel.showMessages(null, [_lang], 'ERROR', function () {
// index. se goi lai trang index. trong do se xoa session & cookie
window.onbeforeunload = null;
window.location = 'index.html?module=login';
});
} else if (jqXHR.status === 503) {
reject(jqXHR, textStatus, errorThrown);
console.log('---service base--503---ko chay reject');
return false;
} else if (jqXHR.status === 0) {
if (jqXHR.statusText === 'canceled') {
_processLoadingImage(false);
return true;
}
reject(jqXHR, textStatus, errorThrown);
var _lang = null;
if (language === 'vn') {
_lang = 'Có lỗi xảy ra - Vui lòng thử lại trong ít phút';
} else {
_lang = 'An error occurred - Please try again in a few minutes';
}
baseModel.showMessages(null, [_lang], 'ERROR', function () {
// index. se goi lai trang index. trong do se xoa session & cookie
history.back();
window.onbeforeunload = null;
});
Constants.currentEntity = jqXHR.getResponseHeader("X-Target-Unit");
// return false;
} else if (jqXHR.status !== 417) {
reject(jqXHR, textStatus, errorThrown);
console.log('---service base--!417---ko chay reject');
return false;
}
});
// //PHUC commment
_processLoadingImage(true);
// Promise.resolve($.ajax(options)).then(resolve, reject);
});
});
};
var _processLoadingImage = function (isstart) {
if (isstart === true) {
counterAjax++;
// console.log('counterAjax start++: ' + counterAjax);
if (counterAjax > 0) {
$('#divOverlay').show();
// var timer = setTimeout(function () { $('#divOverlay').show(); }, 2000);
// clearTimeout(timer);
}
} else {
counterAjax--;
// console.log('counterAjax stop--: ' + counterAjax);
if (counterAjax <= 0) {
counterAjax = 0;
$('#divOverlay').hide();
}
}
};
/**
* The main function which fires the actual batch ajax request.
* This function is called internally from [batch]{@linkcode BaseService#batch}.
* @function fireBatchAjax
* @memberof BaseService
* @inner
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {void}
*/
var fireBatchAjax = function (settings) {
var matches = settings.data.match(/x-nonce:\s(.*?)\r\n/g);
getNonceForServiceInstance((nonceKeys.length - matches.length) < 0 && Math.abs(nonceKeys.length - matches.length));
Promise.all(isNonceFetched).then(function () {
clearIsNonceFetched();
matches.forEach(function (oldNonceHeader) {
settings.data = settings.data.replace(oldNonceHeader, "x-nonce: " + nonceKeys.pop() + "\r\n");
});
var options = $.extend(true, {}, defaults, settings);
var serverURL = platform("getServerURL");
if (serverURL) {
options.url = serverURL + baseUrl + "/batch";
} else {
options.url = baseUrl + "/batch";
}
options.url = addUserLocale(options.url);
platform("addHeader", options.headers);
$.ajax(options).fail(function (jqXHR, textStatus, errorThrown) {
if (jqXHR.status === 417) {
if (jqXHR.responseJSON.message.code === 'DIGX_AUTH_0007') {
baseModel.showMessages(jqXHR, null, null, function () {
history.back();
window.onbeforeunload = null;
});
} else {
baseModel.showAuthScreen(jqXHR, this, this.requestType === "batch" ? fireBatchAjax : this.requestType === "upload" ? batchuploadFile : fireAjax, this.success);
}
return false;
} else {
baseModel.showMessages(jqXHR, null, null, function () {
history.back();
window.onbeforeunload = null;
});
return false;
}
});
});
},
/**
* Generates a random string using Math for use by [batch]{@linkcode BaseService#batch}.
* @function generateRandomString
* @inner
* @memberof BaseService
* @param {Number} length The length of string desired
* @return {String} Random string of desired length is returned.
*/
generateRandomString = (function (length) {
return function () {
return Math.round((Math.pow(36, length + 1) - (Math.random() * Math.pow(36, length)))).toString(36).slice(1);
};
})(10),
/**
* Create payload for batch request.
* @function buildBatchRequest
* @memberof BaseService
* @inner
* @param {Object} data The non-formatted payload parameter sent to buildBatchRequest for formatting.
* @param {String} boundary The boundary string for separating individual requests of batch request.
* @return {Object} The payload object to be fired is returned.
*/
buildBatchRequest = function (data, boundary) {
var payload = "";
var batchPayloadFormat = {
boundary: "--{boundary}\r\n",
header: "{key}: {value}\r\n",
url: "\r\n{methodType} {url} HTTP/{majorminorversion}\r\n",
payload: "\r\n{payload}\r\n",
end: "--{boundary}--\r\n"
};
for (var i = 0; i < data.batchDetailRequestList.length; i++) {
payload += baseModel.format(batchPayloadFormat.boundary, {
boundary: boundary
});
payload += baseModel.format(batchPayloadFormat.header, {
key: "x-nonce",
value: "nonce"
});
for (var key in data.batchDetailRequestList[i].headers) {
if (data.batchDetailRequestList[i].headers.hasOwnProperty(key)) {
payload += baseModel.format(batchPayloadFormat.header, {
key: key,
value: data.batchDetailRequestList[i].headers[key]
});
}
}
payload += baseModel.format(batchPayloadFormat.url, {
methodType: data.batchDetailRequestList[i].methodType,
url: addUserLocale(parameterizeURL(data.batchDetailRequestList[i].uri.value, data.batchDetailRequestList[i].uri.params, true)),
majorminorversion: "1.1"
});
if (data.batchDetailRequestList[i].payload && data.batchDetailRequestList[i].payload.trim())
payload += (baseModel.format(batchPayloadFormat.payload, {
payload: data.batchDetailRequestList[i].payload.trim()
}));
}
return payload += (baseModel.format(batchPayloadFormat.end, {
boundary: boundary
}));
};
self.baseUrl = (self.isMocked ? '../json/' : window.APPLICATION_BASE_URL);
self.baseUrlCz = (self.isMocked ? '../json/' : window.APPLICATION_BASE_URL_CZ);
self.isMocked = false;
/**
* Utility function to parse special characters from received response.
* @inner
* @function characterEncoding
* @memberof BaseService
* @param {Object} obj The object received from response containing special characters.
* @return {Object} The parsed object is returned.
*/
function characterEncoding(obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] === 'object') {
characterEncoding(obj[property]);
} else if (typeof obj[property] === 'string' && obj[property] !== '') {
obj[property] = $('').html(obj[property]).text();
}
}
}
return obj;
}
/**
* Download a file.
* @function downloadFile
* @instance
* @memberof BaseService
* @param {Object} options The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {void}
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/loan/{accountId}/schedule?media=application/pdf&fromDate={fromDate}&toDate={toDate}'
* };
* var params = { 'accountId': accountId, 'fromDate': fromDate, 'toDate': toDate };
* baseService.downloadFile(options, params);
*/
self.downloadFile = function (options, params) {
$('.se-pre-con').show();
options.url = getResourceURL(options.url, options.version);
if (params) {
options.url = parameterizeURL(options.url, params, true);
}
options.url = addUserLocale(options.url);
options.url = normalizeURL(options.url);
if (options.isCustomize) {
options.url = options.url.replace('/digx', '/digx/scb');
} else {
if (options.isRoot) {
options.url = options.url.replace('/digx/v1', '');
}
}
getNonceForServiceInstance();
platform('downloadFile', options, nonceKeys.pop(), genericCompleteHandler);
};
/**
* Fires a POST request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}.
* @function add
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/deposit/{accountId}/penalities',
* data: postDataToBeSent
* };
* var params = { 'accountId': accountId };
* return baseService.add(options, params);
*/
self.add = function (settings, params) {
if (!isMocked) {
settings.type = 'POST';
return fireAjax(settings, params);
}
};
/**
* Fires a batch request for passed parameters. Delegates the ajax call to [fireBatchAjax]{@linkcode BaseService~fireBatchAjax}.
* @function batch
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @param {Object} data The non-formatted payload parameter sent to buildBatchRequest for formatting.
* @returns {void}
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'batch'
* };
* baseService.batch(options, {}, batchRequestData);
*/
self.batch = function (settings, params, data) {
var boundary = "--OBDXbatch" + generateRandomString();
settings.type = "POST";
settings.contentType = "multipart/mixed";
if (settings.headers) {
settings.headers["boundary"] = boundary;
settings.headers["X-BATCH_TYPE"] = params.type;
settings.headers["X-Target-Unit"] = Constants.currentEntity;
} else {
settings.headers = {
"boundary": boundary,
"X-BATCH_TYPE": params.type,
"X-Target-Unit": Constants.currentEntity
};
}
settings.requestType = "batch";
settings.data = buildBatchRequest(data, boundary);
var successHandler = settings.success;
settings.success = function (data, status, jqXHR) {
for (var i = 0; i < data.batchDetailResponseDTOList.length; i++) {
data.batchDetailResponseDTOList[i].responseObj = characterEncoding(JSON.parse(data.batchDetailResponseDTOList[i].responseText));
}
if (successHandler) {
successHandler(data, status, jqXHR);
}
};
fireBatchAjax(settings, params);
};
/**
* Fires an PUT request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}.
* @function update
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/deposit/{accountId}/penalities',
* data: updateData
* };
* var params = { 'accountId': accountId };
* return baseService.update(options, params);
*/
self.update = function (settings, params) {
if (!isMocked) {
settings.type = 'PUT';
return fireAjax(settings, params);
}
};
/**
* Fires a PATCH request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}.
* @function patch
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/deposit/{accountId}/penalities'
* };
* var params = { 'accountId': accountId };
* return baseService.patch(options, params);
*/
self.patch = function (settings, params) {
if (!isMocked) {
settings.type = 'PATCH';
return fireAjax(settings, params);
}
};
/**
* Fires a DELETE request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}.
* @function remove
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/deposit/{accountId}/penalities'
* };
* var params = { 'accountId': accountId };
* return baseService.remove(options, params);
*/
self.remove = function (settings, params) {
if (!isMocked) {
settings.type = 'DELETE';
settings.dataFilter = function (data) {
// console.log('---remove : data' + data);
if (!data) {
return '{}';
}
return data;
};
// console.log('---' + settings.url);
return fireAjax(settings, params);
}
};
/**
* Fires a GET request for passed parameters. Delegates the ajax call to [fireAjax]{@linkcode BaseService~fireAjax}.
* @function fetch
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise returned from [fireAjax]{@linkcode BaseService~fireAjax}.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'accounts/deposit/{accountId}/penalities'
* };
* var params = { 'accountId': accountId };
* return baseService.fetch(options, params);
*/
self.fetch = function (settings, params) {
settings.type = 'GET';
var successHandler = settings.success;
settings.success = function (data, status, jqXHR) {
data = characterEncoding(data);
if (successHandler) {
successHandler(data, status, jqXHR);
}
};
return fireAjax(settings, params);
};
/**
* Fetches a JSON. Uses json plugin of RequireJS to fetch the JSON.
* @function fetchJSON
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {Promise} Returns the promise which resolves or reject when request succeeds or fails respectively.
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'dashboard/{moduleName}'
* };
* var params = { 'moduleName': moduleName };
* return baseService.fetchJSON(options, params);
*/
self.fetchJSON = function (settings, params) {
settings.url = parameterizeURL(settings.url, params, true);
return new Promise(function (resolve) {
require(['json!' + settings.url], function (json) {
resolve(json);
if (settings.success) settings.success(json);
});
});
};
// /**
// * Store Account information
// */
self.storeAccount = function () {
var deferred = $.Deferred();
var options = {
url: "scb/accounts?status=ACTIVE&status=DORMANT",
success: function (data) {
deferred.resolve(data);
},
error: function (data) {
deferred.reject(data);
}
};
if (baseModel.cordovaDevice()) {
window.plugins.appPreferences.fetch('accountData').then((data) => {
if (!data) {
self.fetch(options);
deferred.done(function (d) {
window.plugins.appPreferences.store('accountData', d);
}).fail(function (e) {
console.log(e);
});
}
});
} else if (typeof (Storage) !== "undefined") {
if (!window.sessionStorage.getItem('accountData')) {
self.fetch(options);
deferred.done(function (d) {
window.sessionStorage.setItem('accountData', JSON.stringify(d));
}).fail(function (e) {
console.log(e);
});
}
} else {
// Browser not support Stograge yet
console.log('Browser not support Stograge yet.');
}
};
// /**
// * Get Account storage
// */
// self.getAccountStorage = function (callback) {
// if (baseModel.cordovaDevice()) {
// window.plugins.appPreferences.fetch('accountData').then((data) => {
// callback(data);
// });
// } else if (typeof (Storage) !== "undefined") {
// callback(JSON.parse(window.sessionStorage.getItem('accountData')));
// }
// };
// /**
// * Update Account balance
// */
// self.updateAccountBalance = function (accNum) {
// self.getAccountStorage(function (data) {
// // for(let i in data.accounts){
// // let d = data.accounts[i];
// // if(accNum === d.id.value){
// // d.availableBalance = amount;
// // break;
// // }
// // }
// // calling rest
// var deferred = $.Deferred();
// var options = {
// params: {},
// url: "accounts/demandDeposit/{accNum}",
// success: function (data) {
// deferred.resolve(data);
// },
// error: function (data) {
// deferred.reject(data);
// }
// };
// var params = { 'accNum': accNum };
// self.fetch(options, params);
// deferred.done(function (newData) {
// for (var i in data.accounts) {
// var d = data.accounts[i];
// console.log(newData)
// console.log('--------------')
// if (newData.demandDepositAccountDTO.id.value === d.id.value) {
// console.log('before updating');
// console.log(d);
// d.availableBalance = newData.demandDepositAccountDTO.availableBalance;
// d.currentBalance = newdata.demandDepositAccountDTO.currentBalance;
// d.productDTO = newdata.demandDepositAccountDTO.productDTO;
// d.status = newdata.demandDepositAccountDTO.status;
// console.log('updated: ');
// console.log(d);
// break;
// }
// }
// }).fail(function () {
// console.log('Calling rest to update accountData failture.');
// });
// });
// }
/**
* Uploads a file to the server.
* @function uploadFile
* @memberof BaseService
* @instance
* @param {Object} settings The object containing ajax options. See [ajax settings]{@linkcode http://api.jquery.com/jquery.ajax/#jQuery-ajax-settings} for more details.
* @param {Object} params The parameter object passed for [normalizeURL]{@linkcode BaseService~normalizeURL}.
* @returns {void}
* @example
* var baseService = BaseService.getInstance();
* var options = {
* url: 'brand/{brandId}',
* formData: form,
* type: 'PUT'
* };
* var params = { 'brandId': brandId };
* baseService.uploadFile(options, params);
*/
self.uploadFile = function (settings, params) {
settings.type = "POST";
if (!isMocked) {
var xhr = new XMLHttpRequest(),
response,
// Extend the settings object
// var options = $.extend({}, defaults, settings);
options = $.extend(true, {}, defaults, settings);
//Appending the url with the context
options.url = getResourceURL(options.url, options.version);
if (params) {
options.url = parameterizeURL(options.url, params, true);
}
options.url = addUserLocale(options.url);
options.url = normalizeURL(options.url);
options.requestType = "upload";
// readying xhr for nonce
xhr.open(settings.type || 'POST', options.url, true);
xhr.responseType = 'json';
/*
options.beforeSend(xhr);
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
if (typeof this.response === 'string') {
response = JSON.parse(this.response);
} else {
response = this.response;
}
if (options.success && (this.status === 200 || this.status === 201)) {
options.success(response, this.status, this);
} else if (options.error) {
options.error(response, this.status, this);
}
this.responseJSON = response;
genericCompleteHandler.apply(options, [xhr]);
}
};
xhr.send(options.formData);
*/
options.beforeSend(xhr);
Object.keys(options.headers).forEach(function (key) {
xhr.setRequestHeader([key], options.headers[key]);
});
xhr.send(options.formData);
return new Promise(function (resolve, reject) {
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
if (typeof this.response === "string") {
response = JSON.parse(this.response);
} else {
response = this.response;
}
if (this.status === 200) {
resolve();
} else if (this.status !== 417) {
reject();
}
if (options.success && (this.status === 200 || this.status === 201)) {
options.success(response, this.status, this);
} else if (options.error && this.status !== 417) {
options.error(response, this.status, this);
}
this.responseJSON = response;
genericCompleteHandler.apply(options, [xhr]);
baseModel.checkAndShowError(this);
}
};
});
}
};
/*
Lay danh detail payment de lay duyet cua Doanh Nghiep
*/
var getTransferDataDeferred;
var getTransferData = function (paymentId, deferred) {
// var getTransferDataDeferred = $.Deferred();
// &getAuthType=Y
//&getFee=Y
var url = 'payment/inquiry/' + paymentId + '?status=init&getAuthType=Y&getFee=Y';
var options = {
url: url,
isCustomize: true,
success: function (data) {
deferred.resolve(data);
},
error: function (data) {
deferred.reject(data);
}
};
self.fetch(options);
};
self.getDetailPaymentID = function (myself) {
var paymentId = null;
if (myself.params.transferData && myself.params.transferData.instructionId) {
paymentId = myself.params.transferData.instructionId;
} else if (myself.params.transferData && myself.params.transferData.paymentId) {
paymentId = myself.params.transferData.paymentId;
} else if (myself.params.data) {
paymentId = myself.params.data.paymentId || myself.params.data.instructionId;
} else {
return $.Deferred();
}
// if (!paymentId || paymentId()) {
// return null;
// }
getTransferDataDeferred = $.Deferred();
getTransferData(paymentId(), getTransferDataDeferred);
return getTransferDataDeferred;
// getTransferData(paymentId).done(function (data) {
// selfPaymentData = data;
// }).then(function () {
// return selfPaymentData;
// });
};
/*
self.getNonce = function () {
var nonce;
getNonceForServiceInstance();
if (nonceKeys.length > 0) {
nonce = nonceKeys.pop();
counter++;
}
return nonce;
}; */
/*
*/
self.initLabel = function () {
var ids = document.querySelectorAll('[id$="_LABEL"]');
ids.forEach(item => {
var id_tmp = item.id;
if (!$('#' + id_tmp.replace("_LABEL", ''))[0]) {
console.log(" id_tmp not value : " + id_tmp);
}
// || $('#' + id_tmp.replace("_LABEL", ''))[0].innerText !== ''
if ($('#' + id_tmp.replace("_LABEL", ''))[0] && ($('#' + id_tmp.replace("_LABEL", ''))[0].value.length != "" || ($('#' + id_tmp.replace("_LABEL", ''))[0].type === "select-one" && $('#' + id_tmp.replace("_LABEL", ''))[0].parentNode.innerText != ""))) {
$('#' + item.id).addClass('active');
}
});
};
};
/**
* Holds the instance of [BaseService]{@linkcode BaseService}
* @memberof module:baseService
* @inner
* @type {BaseService}
*/
var instance;
/**
* Creates a instance of service base and returns it.
* @function createInstance
* @memberof module:baseService
* @inner
* @return {BaseService} Instance of service base.
*/
function createInstance() {
var baseService = new BaseService();
/**
* The exported methods of base service.
* @type {Object}
* @name ServiceBaseExports
* @instance
* @property {Function} add - Fires a POST request. See [add]{@linkcode BaseService#add} for detailed usage and documentation.
* @property {Function} patch - Fires a PATCH request. See [patch]{@linkcode BaseService#patch} for detailed usage and documentation.
* @property {Function} fetch - Fires a GET request. See [fetch]{@linkcode BaseService#fetch} for detailed usage and documentation.
* @property {Function} update - Fires an PUT request. See [update]{@linkcode BaseService#update} for detailed usage and documentation.
* @property {Function} remove - Fires a DELETE request. See [remove]{@linkcode BaseService#remove} for detailed usage and documentation.
* @property {Function} batch - Fires a batch request. See [batch]{@linkcode BaseService#batch} for detailed usage and documentation.
* @property {Function} fetchJSON - Fetches a local JSON. See [fetchJSON]{@linkcode BaseService#fetchJSON} for detailed usage and documentation.
* @property {Function} downloadFile - Download a file. See [downloadFile]{@linkcode BaseService#downloadFile} for detailed usage and documentation.
* @property {Function} uploadFile - Upload a file. See [uploadFile]{@linkcode BaseService#uploadFile} for detailed usage and documentation.
*/
var ServiceBaseExports = {
add: baseService.add,
patch: baseService.patch,
fetch: baseService.fetch,
update: baseService.update,
remove: baseService.remove,
batch: baseService.batch,
fetchJSON: baseService.fetchJSON,
downloadFile: baseService.downloadFile,
uploadFile: baseService.uploadFile,
getDetailPaymentID: baseService.getDetailPaymentID,
storeAccount: baseService.storeAccount,
initLabel: baseService.initLabel
};
/*, getNonce: baseService.getNonce */
//
// storeAccount: baseService.storeAccount,
// getAccountStorage: baseService.getAccountStorage,
// updateAccountBalance: baseService.updateAccountBalance
return ServiceBaseExports;
}
return {
/**
* Get the Service Base instance. Checks [instance]{@linkcode module:baseService~instance} for instance. If exists, returns it, else invokes [createInstance]{@linkcode module:baseService~createInstance} to create an instance and returns it.
* @function getInstance
* @memberof module:baseService
* @static
* @returns {BaseService} The base service instance.
*/
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
});